package model

import (
	"go-demo/orm/interval/errs"
	"reflect"
	"unicode"
)

// 我们支持的全部标签上的 key 都放在这里
// 方便用户查找，和我们后期维护
const (
	tagKeyColumn = "column"
)

type Model struct {
	// 结构体对应的表名
	TableName string
	// 数据库字段名 到 类型 的映射
	ColumnMap map[string]*Field
	// go结构体字段名 到 类型的映射
	FieldMap map[string]*Field
}

// Field 字段
type Field struct {
	ColumnName string
	GoName     string
	Type       reflect.Type
	Offset     uintptr
}

func ModelWithTableName(tableName string) ModelOpt {
	return func(model *Model) error {
		model.TableName = tableName
		return nil
	}
}

func ModelWithColumnName(field string, columnName string) ModelOpt {
	return func(model *Model) error {
		fd, ok := model.FieldMap[field]
		if !ok {
			return errs.NewErrUnknownField(field)
		}
		// 注意，这里我们根本没有检测 ColumnName 会不会是空字符串
		// 因为正常情况下，用户都不会写错
		// 即便写错了，也很容易在测试中发现
		fd.ColumnName = columnName
		return nil
	}
}

// TableName 用户实现这个接口来返回自定义的表名
type TableName interface {
	TableName() string
}

// underscoreName 驼峰转字符串命名
func underscoreName(tableName string) string {
	var buf []byte
	for i, v := range tableName {
		if unicode.IsUpper(v) {
			if i != 0 {
				buf = append(buf, '_')
			}
			buf = append(buf, byte(unicode.ToLower(v)))
		} else {
			buf = append(buf, byte(v))
		}

	}
	return string(buf)
}
